package Principal;

import java.math.BigDecimal;
import java.util.List;

public class EventoInicioTransmissao extends Evento{

	public EventoInicioTransmissao(BigDecimal _tempoExecucao, Host _host, HistoriaSimulacao _historiaSimulacao, Estatistica _estatistica, List<Host> _hostsSistema) {
		super(_tempoExecucao, _host, _historiaSimulacao, _estatistica, _hostsSistema);		
	}

	@Override
	public void executar() {
		
		//Se o meio esta livre, transmite dados
		if(host.IsMeiolivre() || host.jaVerifiqueiMeio()){
			
			// Verifico se ja passou o tempo de espera
			if(host.getTempoEspera(tempoExecucao) == BigDecimal.ZERO){
			
				if(verbose){
					System.out.printf("Evento Enviando Pacote. Host: %d. Tempo: %s us.\n", getNumeroHost(), tempoExecucao.setScale(4, BigDecimal.ROUND_HALF_EVEN).toString());
				}
				
				// Calculo o tempo de final de transmissao   
				BigDecimal tempoFinalTransmissao = tempoExecucao.add(host.TEMPO_ENVIO_PACOTE);
				
				// marco na Mensagem os tempos de acesso
				host.setInicioTx(tempoExecucao);
				
				// Armazeno o tempo de inicio de Tx
				host.setTempoUltimoInicioTransmissao(tempoExecucao);
				
				// indico que estou Tx
				host.setTransmitindo();
								
				//Utilizado para retirar o evento final de transmissao Sucesso quando houver colisao
				host.setTempoUltimaTransmissaoHost(tempoFinalTransmissao);
				
				// verifico se o meio esta livre (caso de eventos simultaneos)
				if(host.IsMeiolivre()){
				
					Evento finalTx = new EventoFinalTransmissaoSucesso(tempoFinalTransmissao, host, historiaSimulacao, estatistica, hostsSistema);
					historiaSimulacao.adicionarEvento(finalTx);
					host.coloqueiFimTx();
					
					// Armazeno as informacoes necessarias para o calculo da utilizacao
					if(getNumeroHost() == 1)
					{
						//System.out.printf("Host 1 transmitindo. Tempo: %s us.\n", tempoExecucao.setScale(4, BigDecimal.ROUND_HALF_EVEN).toString());
						estatistica.inicioTx(host, tempoExecucao);
					}
					
					// Gera os eventos para setar o meio ocupado de cada host
					for (Host hostMeioOcupado : hostsSistema) 
					{		
						if(!hostMeioOcupado.equals(host)){				
							BigDecimal tempoEvento = tempoExecucao.add(hostMeioOcupado.getAtrasoPropagacao()).add(host.getAtrasoPropagacao());
							Evento meioOcupado = new EventoMeioOcupado(tempoEvento , hostMeioOcupado, historiaSimulacao, estatistica, hostsSistema);
							historiaSimulacao.adicionarEvento(meioOcupado);
						}						
					}
				}else{
					//se o meio nao esta livre e porque houve uma colisao
					host.incrementarColisao();
					Evento geraColisao = new EventoColisao(tempoExecucao, host, historiaSimulacao, estatistica, hostsSistema);
					historiaSimulacao.adicionarEvento(geraColisao);
				}
			}else{
				// Ainda nao passou o tempo de espera
				// Indico que ja verifiquei o meio
				host.setaVerifiqueiMeio();
				
				// gero um novo evento de inicio de Tx para depois do tempo de espera
				BigDecimal tempoEvento = tempoExecucao.add(host.getTempoEspera(tempoExecucao));
				Evento inicioTx = new EventoInicioTransmissao(tempoEvento, host, historiaSimulacao, estatistica, hostsSistema);
				historiaSimulacao.adicionarEvento(inicioTx);
			}
		}else {
			// Se o meio nao esta livre fico escutando o meio ata ele ficar livre
			if(verbose){
				System.out.printf("Evento Escutando Meio. Host: %d. Tempo: %s us.\n", getNumeroHost(), tempoExecucao.setScale(4, BigDecimal.ROUND_HALF_EVEN).toString());
			}
			host.setInicioTxOcupado(tempoExecucao);
			host.setEscutandoMeio();
		}		
		
	}
	
	

}
